#import <Cocoa/Cocoa.h>
#import <cairo.h>
#import <cairo-quartz.h>

//--------------------------------------------------------------------------
@interface SNsWindow : NSView<NSDraggingDestination>
- (instancetype)initWithFrame:(NSRect)frameRect;

@end

@implementation SNsWindow

- (instancetype)initWithFrame:(NSRect)frameRect{
    self = [super initWithFrame:frameRect];
    NSLog(@"hjx initWithFrame snswindow, self=%p",self);
    return self;
}

-(void)dealloc{
    NSLog(@"hjx dealloc snswindow, self=%p",self);
}

-(BOOL)isFlipped {
return TRUE;
}


-(void) draw:(NSRect) rc : (cairo_t *) cr{

    // 1. 绘制白色背景
    cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); // 白色
    cairo_rectangle(cr, rc.origin.x,rc.origin.y,rc.size.width, rc.size.height);
    cairo_fill(cr);
    

    // 2. 设置红色文本
    const char *text = "Hello, Cairo!";
    cairo_select_font_face(cr, "Arial", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
    cairo_set_font_size(cr, 50.0);
    cairo_set_source_rgb(cr, 1.0, 0.0, 0.0); // 红色
    
    // 计算文本位置（居中）
    cairo_text_extents_t extents;
    cairo_text_extents(cr, text, &extents);
    // 3. 绘制文本
    cairo_move_to(cr, 100, 50);//extents.height + extents.y_bearing);
    cairo_show_text(cr, text);
    
    cairo_set_source_rgb(cr, 1.0, 1.0, 0.0); // 红色
    cairo_rectangle(cr,0,0,50,50);
    cairo_fill(cr);
}

- (void) drawScale:(CGFloat)scaleFactor : (NSRect) rc : (cairo_t *) cr{
    // 1. 创建离屏 Surface
    int width = rc.size.width * scaleFactor;
    int height = rc.size.height * scaleFactor;
    
    cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
    cairo_t * cr2 = cairo_create(surface);
    cairo_scale(cr2, scaleFactor, scaleFactor);
    [self draw: rc : cr2];

    // 2. 绘制到屏幕上
    cairo_set_source_surface(cr, surface, 0, 0);
    cairo_paint(cr);
    
    // 3. 释放资源
    cairo_destroy(cr2);
    cairo_surface_destroy(surface);
}

- (void)drawRect:(NSRect)dirtyRect {
    // 获取当前图形上下文和缩放因子（适配 Retina）
    CGFloat scaleFactor = self.window.backingScaleFactor;
    //scaleFactor = 1;
    NSRect viewBounds = self.bounds;
    // 创建 Cairo 上下文（基于 Quartz）
    CGContextRef cgContext = [[NSGraphicsContext currentContext] CGContext];
    cairo_surface_t *surface = cairo_quartz_surface_create_for_cg_context(
        cgContext,
        viewBounds.size.width,
        viewBounds.size.height
    );
    cairo_t *cr = cairo_create(surface);
    cairo_scale(cr, 1.0f/scaleFactor, 1.0f/scaleFactor);
    [self drawScale:scaleFactor :viewBounds: cr];
 
    // 释放资源
    cairo_destroy(cr);
    cairo_surface_destroy(surface);
}

- (void)mouseExited:(NSEvent *)event {
}

- (void)mouseEntered:(NSEvent *)event {
}

- (void)mouseMoved:(NSEvent *)event { 
}
@end
//--------------------------------------------------------------------------

// 自定义窗口类
@interface SNsWindowHost : NSWindow<NSWindowDelegate>
- (instancetype)initWithContentRect : (NSRect)contentRect
                styleMask:(NSWindowStyleMask)styleMask
                backing:(NSBackingStoreType)backingType
                defer:(BOOL)flag;
-(void)unzoom;
-(void)zoom:(nullable id)sender;
@end

@implementation SNsWindowHost{
    NSRect _rcInit;
    NSView *m_pCapture;
    NSView *m_pHover;
}

- (instancetype)initWithContentRect : (NSRect)contentRect
styleMask:(NSWindowStyleMask)styleMask
backing:(NSBackingStoreType)backingType
defer:(BOOL)flag
{
    self = [super initWithContentRect:contentRect
                            styleMask:styleMask
                              backing:backingType
                                defer:flag];
    [self setAcceptsMouseMovedEvents:YES];
    [self setLevel:(NSWindowLevel)NSNormalWindowLevel];
    [self setDelegate:self]; 
    self.ignoresMouseEvents = NO;
    self.movableByWindowBackground = NO;
    _rcInit = contentRect;
    m_pCapture = nil;
    m_pHover = nil;
    return self;
}

-(void)dealloc{
    NSLog(@"host dealloc, self=%p",self);
}
-(void)unzoom{
    if([self isZoomed]){
        [self setFrame:_rcInit display:YES animate:YES];
    }
}
-(void)zoom:(nullable id)sender{
    if(![self isZoomed]){
        _rcInit = [self frame];
        [super zoom:sender];
    }
}

- (void)sendEvent:(NSEvent *)event {
    if (event.type == NSEventTypeMouseMoved) {
        [self mouseMoved:event];
    }else if(event.type == NSEventTypeLeftMouseDown || event.type == NSEventTypeRightMouseDown || event.type == NSEventTypeOtherMouseDown)
    {
        NSView *view = m_pCapture?m_pCapture:[self.contentView hitTest:event.locationInWindow];
        switch(event.type){
            case NSEventTypeLeftMouseDown:
                [view mouseDown:event];                
                break;
            case NSEventTypeRightMouseDown:
                [view rightMouseDown:event];               
                break;
            case NSEventTypeOtherMouseDown:
                [view otherMouseDown:event];
                break;
            default:
                break;
        }
    }
    else if(event.type==NSEventTypeLeftMouseUp || event.type==NSEventTypeRightMouseUp || event.type==NSEventTypeOtherMouseDragged ){
        NSView *view = m_pCapture?m_pCapture:[self.contentView hitTest:event.locationInWindow];
        switch(event.type){
            case NSEventTypeLeftMouseUp:
                [view mouseUp:event];                
                break;
            case NSEventTypeRightMouseUp:
                [view rightMouseUp:event];               
                break;
            case NSEventTypeOtherMouseUp:
                [view otherMouseUp:event];
                break;
            default:
                break;
        }
    }

    else if(event.type==NSEventTypeLeftMouseDragged || event.type==NSEventTypeRightMouseDragged || event.type==NSEventTypeOtherMouseDragged ){
        [self mouseDragged:event];
    }else if(event.type==NSEventTypeMouseMoved){
        [self mouseMoved:event];
    }
    else
    {
        [super sendEvent:event];
    }
}

-(void)mouseExited:(NSEvent *)event {
    if(!m_pCapture){
        [self.contentView mouseExited:event];
        [[NSCursor arrowCursor] set];
    }
}

- (void)mouseDragged:(NSEvent *)event {
    [self mouseMoved:event];
}

- (void)mouseMoved:(NSEvent *)event{
    if(m_pCapture){
        [m_pCapture mouseMoved:(NSEvent *)event];
        return;
    }
    NSView * pHover = [self.contentView hitTest:event.locationInWindow];
    if(m_pHover != pHover){
        if(m_pHover){
            [m_pHover mouseExited:event];
            m_pHover = nil;
        }
        m_pHover = pHover;
        if(m_pHover){
            [m_pHover mouseEntered:event];
        }
    }
    if(pHover)
    {
        [pHover mouseMoved:(NSEvent *)event];
    }   
}

-(void)close{
    [self setDelegate:nil];
    [super close];
}

@end

//--------------------------------------------------------------------------
@interface AppDelegate : NSObject <NSApplicationDelegate>
@end


@implementation AppDelegate{
    SNsWindowHost *window;
    NSRect  _rcInit;
}

- (void)dealloc{
    NSLog(@"hjx AppDelegate dealloc");
}
- (void)applicationDidFinishLaunching:(NSNotification *)notification {

}

- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
    return YES;
}


-(void) applicationDidResignActive:(NSNotification *)notification {
   NSLog(@"hjx applicationDidResignActive");
}

-(void) applicationDidBecomeActive:(NSNotification *)notification {
   NSLog(@"hjx applicationDidBecomeActive");
}
@end

@interface CMainDlg : NSObject{
    @public
    SNsWindowHost *window;
    NSRect _rcInit;
    BOOL _bQuit;
}
@end

@implementation CMainDlg

-(void)dealloc{
    NSLog(@"hjx CMainDlg dealloc, self=%p", self);
}

-(instancetype)init{
    NSRect rc = NSMakeRect(0,0,400,300);
    NSUInteger style = NSWindowStyleMaskBorderless | NSWindowStyleMaskResizable | NSWindowStyleMaskMiniaturizable;
    window = [[SNsWindowHost alloc] initWithContentRect:rc
                                                  styleMask:style
                                                    backing:NSBackingStoreBuffered
                                                      defer:NO];
    window.backgroundColor = [NSColor windowBackgroundColor];
    
    SNsWindow * swnd = [[SNsWindow alloc] initWithFrame:rc];
    [window setContentView:swnd];
    [window setAnimationBehavior:NSWindowAnimationBehaviorNone];
    
    if (self) {
        NSView *coloredView = [[NSView alloc] initWithFrame:NSMakeRect(50, 0, 50, 50)];
        coloredView.wantsLayer = YES;
        coloredView.layer.backgroundColor = [NSColor redColor].CGColor;
        [window.contentView addSubview:coloredView];
    }

    if (self) {
        // 创建按钮
        NSButton *button = [[NSButton alloc] initWithFrame:NSMakeRect(150, 0, 100, 30)];
        button.title = @"最大化";
        button.bezelStyle = NSBezelStyleRounded;
        button.target = self;
        button.action = @selector(maximizeWindow:);
        
        // 将按钮添加到窗口
        [window.contentView addSubview:button];
    }
    if (self) {
        // 创建按钮
        NSButton *button = [[NSButton alloc] initWithFrame:NSMakeRect(300, 125, 100, 30)];
        button.title = @"还原";
        button.bezelStyle = NSBezelStyleRounded;
        button.target = self;
        button.action = @selector(restoreWindow:);
        
        // 将按钮添加到窗口
        [window.contentView addSubview:button];
    }
    
    if (self) {
        // 创建按钮
        NSButton *button = [[NSButton alloc] initWithFrame:NSMakeRect(125, 200, 100, 30)];
        button.title = @"Quit";
        button.bezelStyle = NSBezelStyleRounded;
        button.target = self;
        button.action = @selector(quit:);
        
        // 将按钮添加到窗口
        [window.contentView addSubview:button];
    }
    
    if (self) {
        // 创建按钮
        NSButton *button = [[NSButton alloc] initWithFrame:NSMakeRect(300, 200, 100, 30)];
        button.title = @"Minimize";
        button.bezelStyle = NSBezelStyleRounded;
        button.target = self;
        button.action = @selector(minimizeWindow:);
        
        // 将按钮添加到窗口
        [window.contentView addSubview:button];
    }
    // 让窗口居中显示
    _rcInit = [window frame];
    [window center];
    [window makeKeyAndOrderFront:nil];
    _bQuit = NO;
    return self;
}

- (void)maximizeWindow:(id)sender {
    _rcInit = [window frame];
    [window zoom:nil];
}

-(void) minimizeWindow:(id)sender{
    [window miniaturize:nil];
}

- (void)restoreWindow:(id)sender {
    [window unzoom];
}

- (void)quit:(id)sender {
    _bQuit = YES;
    //[NSApp terminate:nil];
}

@end


static NSEvent *nextEvent(NSDate *timeoutDate) {
    NSEvent *nsEvent = [NSApp nextEventMatchingMask:NSEventMaskAny
                                          untilDate:timeoutDate
                                             inMode:NSDefaultRunLoopMode
                                            dequeue:YES];
    return nsEvent;
    if (nsEvent == nil)
      return nil;
    NSInteger eventType = nsEvent.type;
    if (eventType == NSEventTypeMouseMoved) {
      NSPoint mouseLocation = [nsEvent locationInWindow];
      if (nsEvent.window != nil) {
        mouseLocation = [nsEvent.window convertPointToScreen:mouseLocation];
      }
      static NSWindow *lastHit = nil;
      // find the window by its mouse location
      NSWindow *wndHit = nil;
      auto windows = [NSApp windows];
      if([windows count] > 0)
      {
        for (int i = [windows count] - 1; i >= 0; i--) {
            auto window = [windows objectAtIndex:i];
            if(![window isVisible])
                continue;
            NSRect frame = [window frame];
            if (NSPointInRect(mouseLocation, frame)) {
                wndHit = window;
                break;
            }
        }
      }
      if(wndHit != lastHit){
        if(lastHit != nil){
          [lastHit mouseExited:nsEvent];
        }
        if(wndHit != nil){
          [wndHit mouseEntered:nsEvent];
        }
        lastHit = wndHit;
      }
      if (wndHit == nil)
        return nil;
      NSInteger windowNumber = [wndHit windowNumber];
      if (windowNumber != nsEvent.windowNumber) {
        NSPoint ptWnd = [wndHit convertPointFromScreen:(NSPoint)mouseLocation];
        nsEvent = [NSEvent mouseEventWithType:NSMouseMoved
                                     location:ptWnd
                                modifierFlags:0
                                    timestamp:0.0
                                 windowNumber:windowNumber
                                      context:nil
                                  eventNumber:0
                                   clickCount:0
                                     pressure:0.0];
      }
    }
    return nsEvent;
}

//--------------------------------------------------------------------------
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSApplication *app = [NSApplication sharedApplication];
        AppDelegate *delegate = [[AppDelegate alloc] init];
        app.delegate = delegate;
        [app setActivationPolicy:NSApplicationActivationPolicyRegular];
        [app activateIgnoringOtherApps:YES];

        // 手动运行自定义事件循环
        BOOL shouldKeepRunning = YES;

        CMainDlg *dlg = [[CMainDlg alloc] init];
        while (shouldKeepRunning) {
            @autoreleasepool {
                // 处理下一个事件（超时时间 0.1 秒，避免 100% CPU 占用）
                NSEvent *event = nextEvent([NSDate dateWithTimeIntervalSinceNow:0.1]);
                if (event) {
                    [NSApp sendEvent:event]; // 分发事件
                    [NSApp updateWindows];
                }
                shouldKeepRunning = !dlg->_bQuit;
            }
        }

        // 正确释放对象：先关闭窗口，再释放对象
        [dlg->window close];
        dlg = nil;
    }
    return 0;
}

